package net.openvision.util.xml;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SAXParser implements XmlParser {

	private javax.xml.parsers.SAXParser parser;
	
	public SAXParser() {
		try {
			parser = SAXParserFactory.newInstance().newSAXParser();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}
	}
	
	private class Handler extends DefaultHandler {
		
		private ElementHandler handler;
		private Object root;
		private Object current;
		
		public Handler(ElementHandler handler) {
			this.handler = handler;
		}
		
		@Override
		public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
			try {
				if (root == null) { // root element
					current = root = handler.elementBegin(localName, attributes);
				} else {
					current = handler.elementBegin(localName, attributes);
				}
			} catch (UnknownElementException e) {
				throw new SAXException(e.getMessage(), e);
			}
			
		}
		
		@Override
		public void endElement(String uri, String localName, String qName) throws SAXException {
			try {
				handler.elementEnd(localName, current);
			} catch (UnknownElementException e) {
				throw new SAXException(e.getMessage(), e);
			}
		}
	}

	@Override
	public Object parse(InputStream istream, ElementHandler handler) throws IOException, XmlParseException {
		try {
			Handler h = new Handler(handler);
			parser.parse(istream, h);
			return h.root;		
		} catch (SAXException e) {
			throw new XmlParseException(e.getMessage(), e);
		}
	}

	@Override
	public Object parse(File file, ElementHandler handler) throws IOException, XmlParseException {
		try {
			Handler h = new Handler(handler);
			parser.parse(file, h);
			return h.root;		
		} catch (SAXException e) {
			throw new XmlParseException(e.getMessage(), e);
		}
	}

	@Override
	public Object parse(InputSource source, ElementHandler handler) throws IOException, XmlParseException {
		try {
			Handler h = new Handler(handler);
			parser.parse(source, h);
			return h.root;		
		} catch (SAXException e) {
			throw new XmlParseException(e.getMessage(), e);
		}
	}

	@Override
	public Object parse(String uri, ElementHandler handler) throws IOException, XmlParseException {
		try {
			Handler h = new Handler(handler);
			parser.parse(uri, h);
			return h.root;		
		} catch (SAXException e) {
			throw new XmlParseException(e.getMessage(), e);
		}
	}
	
}
